public static void main(String args[])
{
(new A()).foo(); // foo from A
(new A()).bar(); // foo from A
(new B()).foo(); // foo from B
(new B()).bar(); // foo from A <- ???
}
}
class A
{
public void foo() {
System.out.println("foo from A");
}
public void bar() {
foo();
}
}
class B extends A
{
public void foo() {
System.out.println("foo from B");
}
public void bar() {
super.foo();
}
}
למה ככה?
9 תשובות
לא הבנתי למה הסימני שאלה שלך. עשית בb.foo קריאה למטודה בparent, עם super. אם תוריד את הsuper. ובעצם תשאיר רק foo(); זה יקרא לb.foo במקום לa.foo
אם תעיף אגב את הדריסה שלך לbar בb, אז b.bar() גם כן ידפיס לך foo from b כמו שאתה רוצה (?).
בכל מקרה,
https://ideone.com/6AlprM
אני יודע שאם אני אוריד את ה-super זה יקרא ל-B.foo.
בדיוק הנקודה שלי. זו ההתנהגות שציפיתי אליה - תמיד קריאה למימוש האחרון, לא? כמו עם המילה השמורה static ב-PHP, וכמו שקורה באופן כללי עם פולימורפיזם.
אגב, למה מה שעשית לא עובד עם פעולות סטטיות?
super קורא למימוש באב, אז כן זה הגיוני למה זה כתב לך foo from A.
וכי אתה לא יכול לדרוס מטודות סטטיות
מעניין. כלומר כשקוראים למתודה שנדרסה, ובעצם מציינים בפירוש לעלות למעלה - גם המימוש עצמו וגם ה-binding עולה למעלה. לאחרון לא ציפיתי, אבל כשחושבים על זה זה דווקא נשמע הגיוני. (לפחות במובן מסוים.)
אני לא קונה את הסיבות שם להיעדרות האפשרות לדרוס מתודות סטטיות. (זה שמדובר במחלקות ולא באובייקטים לא אומר שזה לא הגיוני לדרוס מתודה של מחלקה. זה נשמע מגוחך.) בדקתי בתיעוד הרשמי, וגם שם לא ראיתי הסבר למה זה ככה. יש לך רעיון?
תודה!
בגלל שזה חסר משמעוט מבחינה רעיונית.
הרעיון של דריסה מיועד לפולימורפיזם
כאשר ניתן להפעיל מטודה על מופע מחלקה בלי לדעת את הסוג הספציפי שלה
item.ifaceMethod();
}
כשאתה מפעיל מטודה סטטית - אתה לא מפעיל אותה על מופע מסוים, אלא על טיפוס מסוים, וכשאתה עושה את זה - אתה יודע בוודאות את סוג הטיפוס בזמן כתיבת הקוד.
TypeX.staticM(item);
}
@intval לא בהכרח, אפשר להפעיל על משתנה מסוים (בג'אווה, לפחות). מכיוון שאני אשתמש בזה הרבה פחות (ספק אם בכלל), כי אני נמנע מסטטיות באופן כללי, זה לא כזה חשוב לי, אבל זה כן לא מובן לי.
בנוגע לשאלה המקורית (בערך) - אם אני רוצה כן לדרוס מתודה, ואז לקרוא לה דרך super ולשמור על Binding לאובייקט של מחלקת הבן - אני יכול לעשות את זה? כרגע אני לא מצליח למצוא דוגמה מציאותית לזה, אבל במערכות מורכבות אני בטוח שיש לזה שימושים. (פתרון לזה יכול להיות לשנות את מחלקת האב כדי שתאפשר את זה, אבל לא תמיד זה אפשרי. פתרון אחר הוא להשתמש באותו הקוד של מחלקת האב למתודה הזאת ולהוסיף על זה, אבל זה שכפול קוד.)
אתה מתכוון למשהו כזה בעצם?
public void hello() {
System.out.print("Hello");
}
public void world() {
hello();
}
}
class B extends A {
public void hello() {
super.hello();
System.out.println(" World");
}
}
///
B b = new B();
b.world(); // Hello World
זה בעצם מה שהראית לי בהתחלה. התכוונתי למשהו אחר, אבל בתשובה עם דוגמה שכמעט גמרתי לכתוב לך עכשיו ואז מחקתי, קלטתי שבעיות כאלה אפשר לפתור עם הפרדה פשוטה של מתודות. מובן שאם מדובר במערכת שאי אפשר יהיה לשנות את מחלקת האב זה יהיה קצת בעייתי, אבל זה כבר בעיה של גמישות (וצריך לנסות לעבוד על זה מראש כמה שאפשר), וזה כל מקרה בפני עצמו.
תודה רבה לכם שסבלתם את החפירות שלי. :-)